import cv2 as cv
import numpy as np


# 全局阈值
def threshold_demo(image):
    gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY)  # 把输入图像灰度化
    # 直接阈值化是对输入的单通道矩阵逐像素进行阈值分割。
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
    # (1)参数src表示输入图像（多通道，8位或32位浮点）。
    # (2)参数thresh表示阈值。
    # (3)参数maxval表示与THRESH_BINARY和THRESH_BINARY_INV阈值类型一起使用设置的最大值。
    # (4)type参数表示阈值类型。（后面的cv.THRESH_TRIANGLE表示一种自适应阈值算法）
    # type参数单独选择五种阈值类型时，是固定阈值算法，效果比较差。此外还有自适应阈值算法：（自适应计算合适的阈值，而不是固定阈值）
    # 比如结合cv.THRESH_OTSU，写成cv.THRESH_BINARY | cv.THRESH_OTSU。第二个参数值0可改为任意数字但不起作用。
    # cv.THRESH_OTSU和cv.THRESH_TRIANGLE也可单独使用，不一定要写成和固定阈值算法结合的形式。单独写和结合起来写，都是自适应阈值算法优先。
    # (5)ret表示返回的阈值。若是全局固定阈值算法，则返回thresh参数值。若是全局自适应阈值算法，则返回自适应计算得出的合适阈值。
    # (6)binary表示输出与src相同大小和类型以及相同通道数的图像。
    print("threshold value %s" % ret)
    cv.imshow("binary0", binary)


# 局部阈值
def local_threshold(image):
    gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY)  # 把输入图像灰度化
    # 自适应阈值化能够根据图像不同区域亮度分布，改变阈值
    binary = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 35, 10)
    # src参数表示输入图像（8位单通道图像）。
    # maxValue参数表示使用 THRESH_BINARY 和 THRESH_BINARY_INV 的最大值.
    # adaptiveMethod参数表示自适应阈值算法，平均（ADAPTIVE_THRESH_MEAN_C）或高斯（ADAPTIVE_THRESH_GAUSSIAN_C）。如果使用平均的方法，则所有像素周围的权值相同；如果使用高斯的方法，则每个像素周围像素的权值则根据其到中心点的距离通过高斯方程得到。
    # thresholdType参数表示阈值类型，必须为THRESH_BINARY或THRESH_BINARY_INV的阈值类型。
    # blockSize参数表示块大小（奇数且大于1，比如3，5，7........ ）。
    # C参数是常数，表示从平均值或加权平均值中减去的数。 通常情况下，这是正值，但也可能为零或负值。
    cv.imshow("binary1", binary)


# 用户自己计算阈值
def custom_threshold(image):
    gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY)  # 把输入图像灰度化
    h, w = gray.shape[:2]
    m = np.reshape(gray, [1, w*h])  # 给数组一个新的形状而不改变其数据
    # a参数表示需要重新形成的原始数组。
    # newshape参数表示int或int类型元组（tuple）。
    mean = m.sum()/(w*h)
    print("mean:", mean)
    ret, binary = cv.threshold(gray, mean, 255, cv.THRESH_BINARY)
    cv.imshow("binary2", binary)


# 分块阈值
def big_image_binary(image):
    print(image.shape)
    ch = 55  # 每一块的高度
    cw = 55  # 每一块的宽度
    h, w = image.shape[:2]
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    for row in range(0, h, ch):  # 表示从0开始，一直到h-1（不包含h），步长为ch
        for col in range(0, w, cw):
            roi = gray[row:row+ch, col:col+cw]
            dst = cv.adaptiveThreshold(roi, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 35, 10)  # 也可使用全局阈值
            gray[row:row + ch, col:col + cw] = dst
    cv.imshow("big_image_binary", gray)


src = cv.imread("imgs/test008.jpg")
cv.imshow("bozi", src)
threshold_demo(src)
# local_threshold(src)
# custom_threshold(src)
# big_image_binary(src)
cv.waitKey(0)
cv.destroyAllWindows()
